+function ($) {
	'use strict';
	var Upload = function(e, o) {
		this.o = $.extend({
			'url'			:	'upload.php',
			'auto'			:	true,
			'container'		:	false,
			'method'		:	'POST',
			'name'			:	'file',
			'multiple'		:	false,
			'repeat'		:	false,
			'maxFileSize'	:	false,
			'fileType'		:	false,
			'fileAccept'	:	false,
			'fileLimit'		:	false,
			'imageMinWidth'	:	false,
			'imageMinHeight':	false,
			'imageMaxWidth'	:	false,
			'imageMaxHeight':	false,
			'paramData'		:	function(formData){},
			'identifier'	:	'up_upload_'+Math.round(Math.random()*1000000),
			'beforeSend'	:	function(xhr,data){},
			'selectBefore'	:	function(file){},
			'selectAfter'	:	function(file){},
			'removeFile'	:	function(file){},
			'beforeUpload'	:	function(file,formData){
				this.o.time_now = Date.parse(new Date()) / 1000; 
				if (this.o.token_expire < this.o.time_now + 3){
	                $.ajax({
	                    url:'index/upload/index',
	                    data:{filename:file.name,filesize:file.size,},
	                    async: false,
	                    setting: this,
	                    success:function(s){
	                        if(s.code == -1){
	                            dialog.msg(s);
	                            return false;
	                        }
	                        this.setting.o.formData = s;
	                        this.setting.o.token_expire = s['expire'];
	                        for(var k in s) {
	                        	if(k == 'host'){
	                        		this.setting.o.url = s[k];
	                        	}else{
	                        		formData.append(k, s[k]);
	                        	}
	                        }
	                    }
	                })
	            }else{
                    for(var k in this.o.formData) {
                    	if(k == 'host'){
            				this.o.url = this.o.formData[k];
                    	}else{
                    		formData.append(k, this.o.formData[k]);
                    	}
                    }
	            }
			},
			'uploading'		:	function(file,e){},
			'succeed'		:	function(file,s){},
			'completed'		:	function(file,request,status){},
			'errorUpload'	:	function(file,error){},
			'template'		:	'<div class="up-upload-item" id="[id]"><div class="d-flex justify-content-between bd-highlight"><div>[filename]</div><button type="button" class="btn close" data-file-id="[filesCount]"><span>&times;</span></button></div><div class="progress"><div class="progress-bar progress-bar-striped bg-success progress-bar-animated" style="width: 0%;">0%</div></div></div>',
		}, o,{
			'filesList'			:	[],
			'filesWait'			:	[],
			'filesForbid'		:	[],
			'filesUpload'		:	[],
			'filesComplete'		:	[],
			'filesCount'		:	0,
			'filesValidCount'	:	0,
			'filesUploading'	:	[],
			'e'					:	e ? $(e) : '',
			'error'				:	{'code':0,'msg':''},
			'token_expire'		: 	0,
			'time_now'			: 	Date.parse(new Date()) / 1000,
			'formData'			: 	{},
		});
		if(!this.o.container){
			$(e).after('<div class="up-upload-box" data-container="'+this.o.identifier+'"></div>');
			this.o.container = '[data-container="'+this.o.identifier+'"]';
		}
		$('body').append('<input type="file" id="'+this.o.identifier+'" '+(this.o.multiple ? 'multiple="multiple" ' : '')+' tabindex="-1" '+(this.o.fileAccept ? 'accept="'+this.o.fileAccept+'"' : '')+' style="display:none">');

		$(e).on('click',this,function(e){
			$('#'+e.data.o.identifier).trigger('click');
			return false;
		});
		this.bindInput();
	}
	Upload.prototype = {
		bindInput:function(){
			$('#'+this.o.identifier).off('change').on('change',this,function(e){
				for (var i = this.files.length - 1; i >= 0; i--) {
					e.data.selectFile(this.files[i]);
				}
				$(this).after($(this).clone().val('')).remove();
				e.data.bindInput();
				if(e.data.o.auto){
					e.data.start();
				}
			})
		},
		selectFile : function(file,checkImage){
			var ext = file.name.toLowerCase().split('.').splice(-1)[0],
				allowExt = this.o.fileType ? this.o.fileType.replace(/\s/g,'').toLowerCase().split(',') : false;

	        if(this.o.selectBefore.call(this,file) === false){
	        	return false;
	        }
	        if(this.o.fileLimit && this.o.filesValidCount >= this.o.fileLimit){
	        	return dialog.msg({code:-1,msg:'最多只能上传 '+this.o.fileLimit+' 个文件'});
	        }
			if(allowExt && $.inArray(ext,allowExt) == -1){
				this.o.error.code = -601;
				return this.error(file);
			}
			if(checkImage !== true && (this.o.imageMinWidth || this.o.imageMinHeight || this.o.imageMaxWidth || this.o.imageMaxWidth)){
				if(!/image\/\w+/.test(file.type)){
					this.o.error.code = -601;
					return this.error(file);
				}
				var reader = new FileReader(),
					$_this = this;
				reader.readAsDataURL(file);
				reader.onload = function(e){
					var image = new Image();
					image.src = e.target.result;
					image.onload = function(e){
						if($_this.o.imageMinWidth && $_this.o.imageMinWidth > image.width){
							return dialog.msg({code:-1,msg:'图片最小宽度应大于'+$_this.o.imageMinWidth+'PX'});
						}
						if($_this.o.imageMaxWidth && $_this.o.imageMaxWidth < image.width){
							return dialog.msg({code:-1,msg:'图片最大宽度应小于'+$_this.o.imageMaxWidth+'PX'});
						}
						if($_this.o.imageMinHeight && $_this.o.imageMinHeight > image.height){
							return dialog.msg({code:-1,msg:'图片最小高度应大于'+$_this.o.imageMinHeight+'PX'});
						}
						if($_this.o.imageMaxHeight && $_this.o.imageMaxHeight < image.height){
							return dialog.msg({code:-1,msg:'图片最大高度应小于'+$_this.o.imageMaxHeight+'PX'});
						}
						return $_this.selectFile(file,true);
					}
				}
				return false;
			}
			if(!this.o.repeat){
				for (var i = this.o.filesList.length - 1; i >= 0; i--) {
					if(this.o.filesList[i].name == file.name && this.o.filesList[i].lastModified == file.lastModified && this.o.filesList[i].size == file.size && this.o.filesList[i].type == file.type){
						this.o.error.code = -602;
						return this.error(file);
					}
				}
			}
			if(this.o.maxFileSize){
				this.o.maxFileSize = this.o.maxFileSize.toUpperCase();
				if(this.o.maxFileSize.indexOf('KB') > -1){
					var maxSize = parseInt(this.o.maxFileSize)*1024;
				}else if(this.o.maxFileSize.indexOf('MB') > -1){
					var maxSize = parseInt(this.o.maxFileSize)*1024000;
				}else if(this.o.maxFileSize.indexOf('GB') > -1){
					var maxSize = parseInt(this.o.maxFileSize)*1024000000;
				}
				if(file.size > maxSize){
					this.o.error.code = -600;
					return this.error(file);
				}
			}
			file.id = this.o.identifier+'_item_'+this.o.filesCount;
			file.xhr = false;
			this.o.filesList[this.o.filesCount] = file;
	        if(this.o.selectAfter.call(this,file,this.o.filesCount) !== false && this.o.template){
	        	var template = this.o.template.replace('[filename]',file.name).replace('[id]',file.id).replace('[filesCount]',this.o.filesCount);
	        	$(template).appendTo($(this.o.container));
	        	$('#'+file.id+' .close').on('click',this,function(e){
					e.data.removeFile($(this).data('file-id'));
	        	})
	        }
			this.o.filesCount++;
			this.o.filesValidCount++;
			if(this.o.auto){
				this.start();
			}
		},
		removeFile : function(index){
			var file = this.o.filesList[index];
	        if(this.o.removeFile.call(this,file) === false){
	        	return false;
	        }
	        if(this.o.filesList[index].xhr){
	        	this.o.filesList[index].xhr.abort();
	        }
	        this.o.filesList[index] = false;
			this.o.filesValidCount--;
	        $('#'+file.id).animate({opacity:0},800,function(){
	        	$(this).remove();
	        })
		},
		start: function(){
			for (var i = this.o.filesList.length - 1; i >= 0; i--) {
				if($.inArray(i,this.o.filesComplete) == -1 && (this.o.filesList[i] != false || typeof this.o.filesList[i] == 'object') && !this.o.filesList[i].xhr){
					this.uploadFile(this.o.filesList[i],i);
				}
			}
		},
		stop: function(){
			for (var i = this.o.filesUploading.length - 1; i >= 0; i--) {
				if(this.o.filesList[i].xhr){
					this.o.filesList[i].xhr.abort();
				}
			}
		},
		error : function(file){
	        if(this.o.errorUpload.call(this,file,this.o.error) === false){
	        	return false;
	        }
            switch(this.o.error.code){
            	case -1 :
            		dialog.msg({code:-1,msg:'上传已被取消'});
                    break;
            	case 200 :
                    break;
            	case 203 :
            		dialog.msg({code:-1,msg:'上传成功，但回调失败'});
                    break;
            	case 403 :
            		dialog.msg({code:-1,msg:'无权限上传，请联系管理员'});
                    break;
            	case 404 :
            		dialog.msg({code:-1,msg:'上传地址不存在，请联系管理员'});
                    break;
            	case 500 :
            		dialog.msg({code:-1,msg:'上传地址返回500错误'});
                    break;
                case -600:
                    dialog.msg({code:-1,msg:'文件过大'});
                    break;
                case -601:
                    dialog.msg({code:-1,msg:'不支持该文件类型上传'});
                    break;
                case -602:
                    dialog.msg({code:-1,msg:'该文件已上传过'});
                    break;
                default:
                    dialog.msg({code:-1,msg:'上传时发生了未知错误'});
                    break;
            }
		},
		uploadFile : function(file,index){
			this.o.filesComplete.push(index);
        	var formData = new FormData();
        	if(typeof this.o.paramData == 'function'){
        		this.o.paramData.call(this,formData);
        	}else if(typeof this.o.paramData == 'object'){
            	$.each(this.o.paramData,function(k,v){
            		formData.append(k, v);
            	})
        	}
	        file.item = $(this.o.container).find('#'+file.id);
	        if(this.o.beforeUpload.call(this,file,formData) === false){
	        	return false;
	        }
            formData.append(this.o.name, file);
	        this.o.filesUploading.push(index);
	        this.o.filesList[index].xhr = $.ajax({
	        	url:this.o.url,
	        	type:this.o.method,
				data:formData,
				cache: false,
				contentType: false,
				processData: false,
				setting:this,
	        	beforeSend:function(xhr,data){
					if(typeof this.setting.o.beforeSend == 'function'){
						if(this.setting.o.beforeSend.call(this,xhr,data) === false){
							return false;
						}
					}
	        	},
				success:function(s){
					if(typeof this.setting.o.succeed == 'function'){
						if(this.setting.o.succeed.call(this,file,s) === false){
							return false;
						}
					}
					file.item.find('.progress-bar').html('上传成功').css('width','100%').removeClass('progress-bar-animated');
				},
				complete:function(request, status){
					for (var i = this.setting.o.filesUploading.length - 1; i >= 0; i--) {
						if(this.setting.o.filesUploading[i] == index){
							this.setting.o.filesUploading[i] = null;
						}
					}
					if(typeof this.setting.o.completed == 'function'){
						if(this.setting.o.completed.call(this,file,request,status) === false){
							return false;
						}
					}
					if (request.readyState == 4) {
						switch (request.status){
							case 203:
								this.setting.o.error.code = 203;
								return this.setting.error(file);
								break;
							case 403:
								this.setting.o.error.code = 403;
								return this.setting.error(file);
								break;
							case 404:
								this.setting.o.error.code = 404;
								return this.setting.error(file);
								break;
							case 500:
								this.setting.o.error.code = 500;
								return this.setting.error(file);
								break;
							default:
								this.setting.o.error.code = request.status;
								return this.setting.error(file);
								break;
						}
					}else if(status == 'abort') {
						this.setting.o.error.code = -1;
						return this.setting.error(file);
					}
				},
				xhr:function(){
					var xhr = $.ajaxSettings.xhr(),
						$_this = this;
					if(xhr.upload) {
						xhr.upload.addEventListener('progress' , function(e){
							if(typeof $_this.setting.o.uploading === 'function'){
								if($_this.setting.o.uploading.call($_this,file,e) === false){
									return false;
								}
							}
	                        if (e.lengthComputable) {
	                            var percent = Math.round((e.loaded / e.total) * 100);
	                            file.item.find('.progress-bar').html(percent + '%').css('width', percent + '%');
	                        }
						}, false);
						return xhr;
					}
				}
	        });
		}
	}
	$.fn.uploadFile = function(option) {
		var options = typeof option == 'object' && option;
		if(this.length <= 0){
			return false;
		}else if(this.length == 1){
			var result = new Upload(this, options);
		}else{
			var result = [];
			$.each(this,function(i,v){
				result[i] = new Upload(this, options);
			})
		}
		return result;
	}
}(jQuery);